<template>
    <div class="auth-root-box">
        <section class="tree-box" :class="rightEduTransfer?'half':'all'">
            <p v-if="leftTitle" class="transfer-title">{{leftTitle}}</p>
            <div class="transfer-search">
                <p v-if="leftChecked">
                    <el-checkbox
                        :indeterminate="isLeftIndeterminate"
                        v-model="checkLeft"
                        @change="handleLeftCheckAllChange"
                    >全选</el-checkbox>
                </p>
                <el-input
                    v-if="leftFilter"
                    :placeholder="leftInputPlaceHolder"
                    @focus="leftInputPlaceHolder=''"
                    @blur="leftInputFilter"
                    v-model="leftFilterText"
                ></el-input>

                <div class="select-dept" v-if="leftSearch">
                    <el-select v-model="selectedValue" placeholder="请选择" clearable>
                        <el-option label="全部" value="2"></el-option>
                        <el-option label="学院" value="1"></el-option>
                        <el-option label="非学院" value="0"></el-option>
                    </el-select>
                    <el-button type="primary" @click="searchByType">搜索</el-button>
                </div>
            </div>
            <div class="content">
                <el-tree
                    :style="leftTreeStyle"
                    :data="leftData"
                    :show-checkbox="showCheckBox"
                    :default-expand-all="leftExpandAll"
                    node-key="id"
                    :filter-node-method="filterLeftNode"
                    @check="leftCheckChange"
                    ref="leftTree"
                />
            </div>
        </section>
        <section v-if="rightEduTransfer" class="transfer-box">
            <center>
                <el-button circle class="el-icon-d-arrow-right" @click="addNodes"/>
            </center>
            <br>
            <center>
                <el-button circle class="el-icon-d-arrow-left" @click="removeNodes"/>
            </center>
        </section>
        <section v-if="rightEduTransfer" class="tree-box" :class="rightEduTransfer?'half':'all'">
            <p v-if="rightTitle" class="transfer-title">{{rightTitle}}</p>

            <div class="transfer-search">
                <p v-if="rightChecked">
                    <el-checkbox
                        :indeterminate="isRightIndeterminate"
                        v-model="checkRight"
                        @change="handleRightCheckAllChange"
                    >全选</el-checkbox>
                </p>
                <el-input
                    v-if="rightFilter"
                    :placeholder="rightInputPlaceHolder"
                    @focus="rightInputPlaceHolder=''"
                    @blur="rightInputFilter"
                    v-model="rightFilterText"
                ></el-input>
            </div>
            <div class="content">
                <el-tree
                    :style="rightTreeStyle"
                    :data="rightData"
                    :show-checkbox="showCheckBox"
                    :default-expand-all="rightExpandAll"
                    node-key="id"
                    :filter-node-method="filterRightNode"
                    @check="rightCheckChange"
                    ref="rightTree"
                />
            </div>
        </section>
    </div>
</template>

<script>
export default {
    name: "EduTransfer",

    data() {
        return {
            leftInputPlaceHolder: "输入关键字进行过滤",
            rightInputPlaceHolder: "输入关键字进行过滤",
            leftFilterText: "",
            rightFilterText: "",
            searchType: "",
            defaultProps: {
                children: "children",
                label: "label"
            },
            checkLeft: false,
            checkRight: false,
            isLeftIndeterminate: false,
            isRightIndeterminate: false,
            keys: {},
            selectedValue: "",
            leftTreeStyle: "",
            rightTreeStyle: ""
        };
    },
    props: {
        leftExpandAll: {
            default: false,
            type: Boolean
        },
        rightExpandAll: {
            default: false,
            type: Boolean
        },
        showCheckBox: {
            default: true,
            type: Boolean
        },
        rightEduTransfer: {
            default: true,
            type: Boolean
        },
        leftSearch: {
            default: false,
            type: Boolean
        },
        leftFilter: {
            default: false,
            type: Boolean
        },
        leftChecked: {
            default: false,
            type: Boolean
        },
        rightChecked: {
            default: false,
            type: Boolean
        },
        rightFilter: {
            default: false,
            type: Boolean
        },
        leftTitle: {
            default: "",
            type: String
        },
        leftTransferData: {
            default: "",
            type: String
        },
        rightTitle: {
            default: "",
            type: String
        },
        rightTransferData: {
            default: "",
            type: String
        },
        selectedBySearch: {
            default: false,
            type: Boolean
        }
    },
    computed: {
        rightData() {
            this.rightFilterText = "";
            this.checkRight = false;
            this.isRightIndeterminate = false;
            if (this.rightTransferData && this.rightTransferData !== "[]") {
                let data = JSON.parse(this.rightTransferData);
                let { selfId, selfName, parentName } = this.resolveKey(data);
                let newData = data.filter(el => {
                    if (el[parentName] === -1) {
                        el.label = el[selfName];
                        el.id = el[selfId];
                        el.children = [];
                        return el;
                    }
                });
                let list = this.dealList(
                    parentName,
                    selfId,
                    selfName,
                    newData,
                    data
                );
                return list;
            } else {
                this.checkRight = false;
                return [];
            }
        },
        leftData() {
            this.leftFilterText = "";
            this.checkLeft = false;
            this.isLeftIndeterminate = false;
            if (
                this.leftTransferData.length &&
                this.leftTransferData !== "[]"
            ) {
                let data = [];
                let initData = JSON.parse(this.leftTransferData);
                if (this.searchType == "") {
                    data = initData;
                } else {
                    data = initData.filter(item => {
                        return item.isFaculty == this.searchType;
                    });
                }
                let { selfId, selfName, parentName } = this.resolveKey(data);
                let newData = data.filter(el => {
                    if (el[parentName] === -1) {
                        el.label = el[selfName];
                        el.id = el[selfId];
                        el.children = [];
                        return el;
                    }
                });
                let list = this.dealList(
                    parentName,
                    selfId,
                    selfName,
                    newData,
                    data
                );
                return list;
            } else {
                return [];
            }
        }
    },
    mounted() {
        let leftCount = 0;
        if (this.leftTitle) {
            leftCount++;
        }
        if (this.leftChecked || this.leftFilter || this.leftSearch) {
            leftCount++;
        }
        let leftHeight = 360 - leftCount * 36 + "px";
        this.leftTreeStyle = {
            height: leftHeight
        };
        let rightCount = 0;
        if (this.rightTitle) {
            rightCount++;
        }
        if (this.rightChecked || this.rightFilter || this.rightSearch) {
            rightCount++;
        }
        let rightHeight = 360 - rightCount * 36 + "px";
        this.rightTreeStyle = {
            height: rightHeight
        };
    },
    methods: {
        leftInputFilter() {
            if (
                this.leftFilterText === "" ||
                this.leftFilterText === undefined
            ) {
                this.leftInputPlaceHolder = "输入关键字进行过滤";
            }
        },
        rightInputFilter() {
            if (
                this.rightFilterText === "" ||
                this.rightFilterText === undefined
            ) {
                this.rightInputPlaceHolder = "输入关键字进行过滤";
            }
        },
        resolveKey(data) {
            if (JSON.stringify(this.keys) !== "{}") {
                return this.keys;
            }
            //用来对接口数据进行解析，获取父节点名称parentName，需要展示的数据selfName和展示数据对应的selfId
            let keys = Object.keys(data[0]).filter(el => {
                return el.startsWith("parent") && el.endsWith("Id");
            });
            let selfId = null;
            let selfName = null;
            let language = this.$store.state.language;
            if (keys[0] === "parentId") {
                selfId = "valueId";
                if (language === "cn") {
                    selfName = "valueName";
                } else {
                    selfName = "valueNameEn";
                }
            } else if (keys[0] === "parentAuthId") {
                selfId = "authId";
                if (language === "cn") {
                    selfName = "authNameCh";
                } else {
                    selfName = "authNameEn";
                }
            } else if (keys[0] === "parentDeptId") {
                selfId = "deptId";
                if (language === "cn") {
                    selfName = "deptName";
                } else {
                    selfName = "deptNameEn";
                }
            }
            this.keys = {
                selfId,
                selfName,
                parentName: keys[0]
            };
            return this.keys;
        },
        handleLeftCheckAllChange(e) {
            // 全选与反选
            this.checkLeft = e;
            if (e) {
                this.$refs.leftTree.setCheckedNodes(this.leftData);
                this.isLeftIndeterminate = false;
            } else {
                this.$refs.leftTree.setCheckedNodes([]);
                this.isLeftIndeterminate = false;
            }
            this.leftCheckChange();
        },
        handleRightCheckAllChange(e) {
            // 全选与反选
            this.checkRight = e;
            if (e) {
                this.$refs.rightTree.setCheckedNodes(this.rightData);
                this.isRightIndeterminate = false;
                this.rightExpandAll = true;
            } else {
                this.$refs.rightTree.setCheckedNodes([]);
                this.isRightIndeterminate = false;
                this.rightExpandAll = false;
            }
            this.rightCheckChange();
        },
        dealList(parentName, selfId, selfName, newData, data) {
            let list = newData.map(item => {
                let children = data.filter(e => {
                    if (item[selfId] === e[parentName]) {
                        e.label = e[selfName];
                        e.id = e[selfId];
                        e.children = [];
                        return item.children.push(e);
                    }
                });
                this.dealList(parentName, selfId, selfName, children, data);
                return item;
            });
            return list;
        },
        getCheckedId(selfId, parentName, item, data) {
            // 对选中的节点进行解析，返回选中节点的ID
            let newArr = [];
            let list = data.forEach(el => {
                if (el[selfId] === item[parentName]) {
                    if (el[parentName] !== -1) {
                        newArr.push(el[selfId]);
                        let arr = this.getCheckedId(
                            selfId,
                            parentName,
                            el,
                            data
                        );
                        newArr = [...newArr, ...arr];
                    }
                    newArr.push(el[selfId]);
                }
            });
            return newArr;
        },
        dealCheckedNodes(checkedList, data) {
            //获取选中的节点父ID并返回
            let { parentName, selfId } = this.keys;

            let arr = [];
            let initData = JSON.parse(data);
            checkedList.forEach(item => {
                if (item[parentName] !== -1) {
                    let newArr = this.getCheckedId(
                        selfId,
                        parentName,
                        item,
                        initData
                    );
                    arr = [...newArr, ...arr];
                }
                arr.push(item[selfId]);
            });
            let result = Array.from(new Set(arr));
            return result;
        },
        resolveAddData(data, source, target) {
            let { selfId } = this.keys;
            // 解析选中的ID对应的数据
            let newArr = JSON.parse(target).filter(item => {
                if (data.indexOf(item[selfId]) > -1) {
                    return item;
                }
            });

            let arr = [];
            if (source) {
                arr = JSON.parse(source).filter(item => {
                    if (data.indexOf(item[selfId]) === -1) {
                        return item;
                    }
                });
            }
            let result = [...newArr, ...arr];
            return JSON.stringify(result);
        },
        resolveDelData(data, source) {
            let { selfId } = this.keys;
            // 从源数据侧删除选中的节点数据
            let result = JSON.parse(source).filter(item => {
                if (data.indexOf(item[selfId]) === -1) {
                    return item;
                }
            });
            return JSON.stringify(result);
        },
        getFilterCheckedList(ref, filterText, selfName) {
            if (this.selectedBySearch) {
                return this.$refs[ref].getCheckedNodes().filter(item => {
                    if (!filterText && filterText != 0) {
                        return item;
                    } else {
                        return item[selfName].includes(filterText);
                    }
                });
            } else {
                return this.$refs[ref].getCheckedNodes();
            }
        },
        addNodes() {
            // 解析选中的节点以及父节点的id
            let { selfId, selfName } = this.keys;
            let checkedList = this.getFilterCheckedList(
                "leftTree",
                this.leftFilterText,
                selfName
            );
            if (checkedList.length == 0) {
                return;
            }
            let json = {
                result: [],
                rightUpdateData: "",
                leftUpdateData: ""
            };
            let updateList = this.dealCheckedNodes(
                checkedList,
                this.leftTransferData
            );
            // 组装右侧更新后的数据
            json.rightUpdateData = this.resolveAddData(
                updateList,
                this.rightTransferData,
                this.leftTransferData
            );
            json.resultWithParent = updateList;
            json.result = checkedList.map(el => {
                return el[selfId];
            });
            // 组装左侧更新后的数据
            json.leftUpdateData = this.resolveDelData(
                updateList,
                this.leftTransferData
            );
            this.$emit("addNodesToRight", json);
        },
        removeNodes() {
            // 解析选中的节点以及父节点的id
            let { selfId, selfName } = this.keys;
            let checkedList = this.getFilterCheckedList(
                "rightTree",
                this.rightFilterText,
                selfName
            );
            if (checkedList.length == 0) {
                return;
            }
            let json = {
                result: [],
                rightUpdateData: "",
                leftUpdateData: ""
            };
            let updateList = this.dealCheckedNodes(
                checkedList,
                this.rightTransferData
            );
            // 组装左侧更新后的数据
            json.leftUpdateData = this.resolveAddData(
                updateList,
                this.leftTransferData,
                this.rightTransferData
            );
            // 组装右侧更新后的数据
            json.rightUpdateData = this.resolveDelData(
                updateList,
                this.rightTransferData
            );
            json.resultWithParent = updateList;
            json.result = checkedList.map(el => {
                return el[selfId];
            });
            this.$emit("delNodesFromRight", json);
        },
        filterLeftNode(value, leftTransferData) {
            if (!value) return true;
            return leftTransferData.label.indexOf(value) !== -1;
        },
        filterRightNode(value, rightTransferData) {
            if (!value) return true;
            return rightTransferData.label.indexOf(value) !== -1;
        },
        leftCheckChange() {
            let { selfId, selfName } = this.keys;
            let checkedList = this.getFilterCheckedList(
                "leftTree",
                this.leftFilterText,
                selfName
            );
            let checkedNodes = this.dealCheckedNodes(
                checkedList,
                this.leftTransferData
            );
            let len = checkedNodes.length;
            let oldLen = 0;
            if (this.selectedBySearch) {
                oldLen = this.leftData.filter(item => {
                    return item.label.indexOf(this.leftFilterText) !== -1;
                }).length;
            } else {
                oldLen = JSON.parse(this.leftTransferData).length;
            }
            if (oldLen === 0) {
                this.isLeftIndeterminate = false;
                this.checkLeft = false;
            } else if (len === oldLen) {
                this.isLeftIndeterminate = false;
                this.checkLeft = true;
            } else if (len === 0) {
                this.isLeftIndeterminate = false;
                this.checkLeft = false;
            } else {
                this.isLeftIndeterminate = true;
            }
            this.$emit("checkChange", checkedNodes);
        },
        rightCheckChange() {
            let { selfId, selfName } = this.keys;
            let checkedList = this.getFilterCheckedList(
                "rightTree",
                this.rightFilterText,
                selfName
            );
            let checkedNodes = this.dealCheckedNodes(
                checkedList,
                this.rightTransferData
            );
            let len = checkedNodes.length;

            let oldLen = 0;
            if (this.selectedBySearch) {
                oldLen = this.rightData.filter(item => {
                    return item.label.indexOf(this.rightFilterText) !== -1;
                }).length;
            } else {
                oldLen = JSON.parse(this.rightTransferData).length;
            }
            if (oldLen === 0) {
                this.isLeftIndeterminate = false;
                this.checkLeft = false;
            } else if (len === oldLen) {
                this.isRightIndeterminate = false;
                this.checkRight = true;
            } else if (len === 0) {
                this.isRightIndeterminate = false;
                this.checkRight = false;
            } else {
                this.isRightIndeterminate = true;
            }
        },
        searchByType() {
            let value = this.selectedValue == 2 ? "" : this.selectedValue;
            this.searchType = value;
        }
    },
    watch: {
        leftFilterText(val) {
            this.handleLeftCheckAllChange(false);
            this.$refs.leftTree.filter(val);
        },
        rightFilterText(val) {
            this.handleRightCheckAllChange(false);
            this.$refs.rightTree.filter(val);
        }
    }
};
</script>


<style lang="scss" scoped>
.auth-root-box {
    padding: 0;
    margin: 0;
    height: 360px;
    section {
        overflow: hidden;
        height: 100%;
        float: left;
        .left-text {
            height: 30px !important;
        }
    }
    section.half {
        width: 45%;
    }
    section.all {
        width: 100%;
    }
    section.tree-box {
        border: 1px solid #e5e5e5;
        border-radius: 2px;
        .transfer-title {
            background-color: #eee;
            margin: 0px;
            color: #303133;
            margin: 0;
            padding: 0;
            height: 36px;
            line-height: 36px;
            font-weight: 600;
            border-bottom: 1px solid #e5e5e5;
            padding-left: 12px;
        }
        .transfer-search {
            background-color: #eee;
            display: flex;
            overflow: hidden;
            .select-dept {
                flex: 3;
                flex-shrink: 1;
                margin-left: 10px;
                display: flex;
                overflow: hidden;
                .el-select {
                    flex: 2;
                    flex-basis: 40px;
                    height: 34px !important;
                    overflow: hidden;
                    border: 1px solid #ddd;
                }
                .el-button {
                    flex: 1;
                    padding: 0;
                    min-width: 10px !important;
                }
            }
            .el-input {
                flex: 2;
                flex-shrink: 1;
                overflow: hidden;
            }
            p {
                flex: 1 0 25px;
                margin: 0;
                padding: 0;
                height: 36px;
                line-height: 36px;
                font-weight: 600;
                border: 1px solid #e5e5e5;
                padding-left: 12px;
                background: #eee;
            }
            .content {
                overflow: hidden;
                height: 100%;
            }
        }
        div {
            width: 100%;
            overflow: auto;
        }
        .el-tree {
            padding: 5px;
        }
    }
    section.transfer-box {
        width: 8%;
        padding-top: 120px;
        .el-button {
            margin-bottom: 10px;
        }
    }
}
</style>
